home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 June / MacFormat 25.iso / Shareware City / Developers / GlueWindow4.1(source) Folder / Source(THINK C7.0) / GlueWindowINIT4.1.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-07  |  33.3 KB  |  1,157 lines  |  [TEXT/KAHL]

  1. //    GlueWindowINIT4.1.c
  2.  
  3. //    inclusion of files ------------------------------
  4.  
  5. #include    <SetUpA4.h>                //    To use globals in INIT.
  6. #include    <OSUtils.h>                //    To check whether Gestalt is available or not.
  7. #include    <Sound.h>                //    To use sound resources.
  8. #include    "GlueWindow4.1.h"        //    Inclusion of definition.
  9.  
  10. //    definition --------------------------------------
  11.  
  12. #define        key1        (**setting_hdl).push_key
  13. #define        key2        (**setting_hdl).pop_key
  14. #define        key3        (**setting_hdl).drag_key
  15. #define        gray_rect    my_qd_globals.screenBits.bounds
  16. #define        PUSH_RSRC    0
  17. #define        POP_RSRC    1
  18. #define        menu_bar_height        20
  19.  
  20. //    declaration of prototypes -----------------------
  21.  
  22. int abs(int i);
  23.  
  24. pascal Boolean    (*TrackGoAwayProc)    (WindowPtr wp, Point mp);
  25. pascal void     (*DragWindowProc)    (WindowPtr wp, Point mp, Rect *r);
  26. pascal long     (*GrowWindowProc)    (WindowPtr wp, Point mp, Rect *r);
  27.  
  28. pascal void call_push_window(WindowPtr wp, Point mp, Rect *r);
  29. pascal void call_pop_window (WindowPtr wp, Point mp, Rect *r);
  30.  
  31. pascal Boolean call_original_go_away(WindowPtr wp, Point mp);
  32. pascal Boolean call_custom_go_away    (WindowPtr wp, Point mp);
  33. pascal Boolean my_track_go_away        (WindowPtr wp, Point mp);
  34.  
  35.  
  36. pascal void call_no_marquee_drag(WindowPtr wp, Point mp, Rect *r);
  37. pascal void call_original_drag    (WindowPtr wp, Point mp, Rect *r);
  38. pascal void call_custom_drag    (WindowPtr wp, Point mp, Rect *r);
  39. pascal void my_drag_window        (WindowPtr wp, Point mp, Rect *r);
  40.  
  41. pascal long call_original_grow    (WindowPtr wp, Point mp, Rect *r);
  42. pascal long call_custom_grow    (WindowPtr wp, Point mp, Rect *r);
  43. pascal long my_grow_window        (WindowPtr wp, Point mp, Rect *r);
  44.  
  45. void    draw_marquee(Rect *marquee, Rect *gap);
  46. void    copy_pattern(Pattern src_pat, Pattern dst_pat);
  47.  
  48.  
  49. pascal Handle    Get1Resource_in_system_heap(OSType rType, short id);
  50. pascal OSErr    my_gestalt_selector(OSType selector, long *responce);
  51. void            set_my_selector(ProcPtr func_address);
  52.  
  53. short        NumToolboxTraps( void );
  54. TrapType    GetTrapType(short theTrap);
  55. Boolean        TrapAvailable(short theTrap);
  56.  
  57. init_data_hdl    load_setting(void);
  58. void            save_setting(init_data_hdl sysheap_data_hdl, prefs_file *pf);
  59. int                open_prefs_file(prefs_file *pf);
  60. void            show_loading_icon(short which_icon);
  61. void            do_loading(void);
  62. Boolean            is_system7(void);
  63.  
  64. void main(void);
  65.  
  66. //    declaration of globals --------------------------
  67.  
  68. qd_globals        my_qd_globals;
  69. init_data_hdl    setting_hdl = nil;
  70. Handle            my_push_snd_hdl = nil;
  71. Handle            my_pop_snd_hdl = nil;
  72.  
  73. // main routines -----------------------------------
  74.  
  75. void main(void)
  76. {
  77.     RememberA0();    //    RememberA0(), SetUpA4() and RestoreA4() are keywords 
  78.     SetUpA4();        //    to use globals in code resources with THINK C.
  79.     
  80.     if(is_system7()) {
  81.         InitGraf(&my_qd_globals.thePort);                                                //    This initialization is to show the startup icon.
  82.         do_loading();
  83.     }
  84.     RestoreA4();
  85. }
  86.  
  87. Boolean is_system7(void)
  88. {
  89.     Boolean    f;
  90.     OSErr    err;
  91.     long    r;
  92.     
  93.     if(f = TrapAvailable(_Gestalt)) {
  94.             //    You have to check like this before using Gestalt.
  95.         err = Gestalt(gestaltSystemVersion, &r);
  96.         if(err != noErr)    f = false;
  97.         else if(r <0x0700) f = false;
  98.         else f = true;
  99.     }
  100.     return(f);
  101. }
  102.  
  103. void do_loading(void)
  104. {
  105.     short        icon_number = SHOW_OK_ICON;
  106.     Handle        h;
  107.     Rect        r;
  108.     long        drag_address, grow_address, away_address;
  109.     ProcPtr        selector_func_address;
  110.     
  111.     h = Get1Resource_in_system_heap('INIT', RSRC_NUMBER_BASE);
  112.     if(h) {
  113.         setting_hdl = load_setting();
  114.         if(setting_hdl) {
  115.             DetachResource(h);    //    If you don't detach, 
  116.             HLock(h);            //    resources are purged at the end of INIT.
  117.             HNoPurge(h);
  118.             
  119.             //    You can use 'trapped' system routines with following procedures. 
  120.             
  121.             away_address = NGetTrapAddress(_TrackGoAway, ToolTrap);
  122.             drag_address = NGetTrapAddress(_DragWindow, ToolTrap);
  123.             grow_address = NGetTrapAddress(_GrowWindow, ToolTrap);
  124.             
  125.             TrackGoAwayProc = (pascal Boolean (*)(WindowPtr, Point))away_address;
  126.             DragWindowProc = (pascal void (*)(WindowPtr, Point, Rect*))drag_address;
  127.             GrowWindowProc = (pascal long (*)(WindowPtr, Point, Rect*))grow_address;
  128.             
  129.             NSetTrapAddress((long) my_track_go_away, _TrackGoAway, ToolTrap);
  130.             NSetTrapAddress((long) my_drag_window, _DragWindow, ToolTrap);
  131.             NSetTrapAddress((long) my_grow_window, _GrowWindow, ToolTrap);
  132.             
  133.             if(TrapAvailable(_SndPlay)) {    //    To use sound routines, you must check.
  134.                 my_push_snd_hdl = Get1Resource_in_system_heap('snd ',
  135.                                                 RSRC_NUMBER_BASE + PUSH_RSRC);
  136.                 if(my_push_snd_hdl) {
  137.                     DetachResource(my_push_snd_hdl);
  138.                     HLock(my_push_snd_hdl);
  139.                     HNoPurge(my_push_snd_hdl);
  140.                     my_pop_snd_hdl = Get1Resource_in_system_heap('snd ',
  141.                                                 RSRC_NUMBER_BASE + POP_RSRC);
  142.                     if(my_pop_snd_hdl) {
  143.                         DetachResource(my_pop_snd_hdl);
  144.                         HLock(my_pop_snd_hdl);
  145.                         HNoPurge(my_pop_snd_hdl);
  146.                     }
  147.                 }
  148.             }
  149.             selector_func_address = (ProcPtr)my_gestalt_selector; 
  150.             set_my_selector(selector_func_address);
  151.             if(!(**setting_hdl).show_init_icon) {
  152.                 icon_number = SHOW_NO_ICON;
  153.             }
  154.         } 
  155.         else {
  156.             icon_number = SHOW_NG_ICON;
  157.             ReleaseResource(h);
  158.                 //    If loading is failed, the 'INIT' resource is released.
  159.         }
  160.     } else        icon_number = SHOW_NG_ICON;
  161.     show_loading_icon(icon_number);
  162. }
  163.  
  164. void show_loading_icon(short which_icon)
  165. {
  166.     Handle        icon_h = nil;
  167.     GrafPtr        saved_port;
  168.     GrafPort    temp_port;
  169.     Rect        r;
  170.     short        screen_width;
  171.     Boolean        color_icon;
  172.  
  173.     if(which_icon != SHOW_NO_ICON) {
  174.         color_icon = TrapAvailable(_GetCIcon);
  175.             //    Sometimes you can't use 'cicn' color icon resources
  176.             //    because GetCIcon and PlotCIcon are not implemented.    
  177.         if(color_icon)
  178.             icon_h = (Handle)GetCIcon(RSRC_NUMBER_BASE + which_icon);
  179.         else
  180.             icon_h = GetIcon(RSRC_NUMBER_BASE + which_icon);
  181.         if(icon_h) {
  182.             HNoPurge(icon_h);
  183.             GetPort(&saved_port);
  184.             OpenPort(&temp_port);
  185.             SetPort(&temp_port);
  186.             if(((icon_loc_h << 1) ^ 0x1021) != icon_loc_cs) icon_loc_h = 8;
  187.             screen_width =  ((temp_port.portRect.right    -
  188.                               temp_port.portRect.left)    / 40) * 40;
  189.             r.left    = icon_loc_h % screen_width;
  190.             r.right    = r.left + 32;
  191.             r.top    = temp_port.portRect.bottom -
  192.                         (40 * (1 + icon_loc_h / screen_width));
  193.             r.bottom = r.top + 32;
  194.             if(color_icon)
  195.                 PlotCIcon(&r, (CIconHandle)icon_h);
  196.             else
  197.                 PlotIcon(&r, icon_h);
  198.             icon_loc_h += 40;
  199.             icon_loc_cs = (icon_loc_h<<1) ^ 0x1021;
  200.             if(color_icon)
  201.                 DisposeCIcon((CIconHandle)icon_h);
  202.             else
  203.                 DisposeHandle(icon_h);
  204.             SetPort(saved_port);
  205.             ClosePort(&temp_port);
  206.         }
  207.     }
  208. }
  209.  
  210. //    gestalt check routines ----------------------------------
  211.  
  212. #define TrapMask 0x0800
  213.  
  214. short NumToolboxTraps( void )
  215. {
  216.     if (NGetTrapAddress(_InitGraf, ToolTrap) ==
  217.             NGetTrapAddress(0xAA6E, ToolTrap))
  218.         return(0x0200);
  219.     else
  220.         return(0x0400);
  221. }
  222.  
  223. TrapType GetTrapType(short theTrap)
  224. {
  225.  
  226.     if ((theTrap & TrapMask) > 0)
  227.         return(ToolTrap);
  228.     else
  229.         return(OSTrap);
  230.  
  231. }
  232.  
  233. Boolean TrapAvailable(short theTrap)
  234. {
  235.  
  236.     TrapType    tType;
  237.  
  238.     tType = GetTrapType(theTrap);
  239.     if (tType == ToolTrap)
  240.     theTrap = theTrap & 0x07FF;
  241.     if (theTrap >= NumToolboxTraps())
  242.         theTrap = _Unimplemented;
  243.  
  244.     return (NGetTrapAddress(theTrap, tType) !=
  245.             NGetTrapAddress(_Unimplemented, ToolTrap));
  246. }
  247.  
  248. //    setting gestalt routines -------------------------
  249.  
  250. void set_my_selector(ProcPtr func_address)
  251. {
  252.     OSErr    er;
  253.     
  254.     if(TrapAvailable(_Gestalt)) {
  255.         SetUpA4();
  256.         er = NewGestalt(CREATOR, func_address);
  257.             //    To hand address of INIT globals to cdev, you can use NewGestalt.
  258.         RestoreA4();
  259.     }
  260. }
  261.  
  262. pascal OSErr my_gestalt_selector(OSType selector, long *responce)
  263. {
  264.     SetUpA4();
  265.     *responce = (long)setting_hdl;
  266.     RestoreA4();    //    All you have to do is wriiten here.
  267.     return(NO_ERROR);
  268. }
  269.  
  270. pascal Handle Get1Resource_in_system_heap(OSType rType, short id)
  271. {
  272.     THz        oldZone;
  273.     Handle    h;
  274.  
  275.     oldZone = GetZone();
  276.     SetZone(SystemZone());
  277.     h = Get1Resource(rType, id);
  278.     SetZone(oldZone);
  279.     return(h);
  280. }
  281.  
  282. //    data routines -----------------------------------
  283.  
  284. init_data_hdl load_setting(void)
  285. {
  286.     init_data_hdl        h = nil, work_h = nil;
  287.     old_init_data_hdl    old_h;
  288.     prefs_file            pf;
  289.     int                    er;
  290.     short                saved_ref_num;
  291.     
  292.     saved_ref_num = CurResFile();
  293.     er = open_prefs_file(&pf);
  294.         //    pf is struct which contains all parameters to use preferences file.
  295.     if(er == NO_ERROR) {
  296.         h = (init_data_hdl)Get1Resource_in_system_heap(SETTING_RSRC, RSRC_NUMBER_BASE + 1);
  297.         if(h) {
  298.             HNoPurge((Handle)h);
  299.             DetachResource((Handle)h);
  300.         }
  301.         else {
  302.             old_h = (old_init_data_hdl)Get1Resource(SETTING_RSRC, RSRC_NUMBER_BASE);
  303.             if(old_h) {
  304.                 h = (init_data_hdl)NewHandleSys(sizeof(init_data));
  305.                 if(h) {
  306.                     (**h).drag_on        = (**old_h).drag_on;
  307.                     (**h).grow_on        = (**old_h).grow_on;
  308.                     (**h).push_on        = (**old_h).push_on;
  309.                     (**h).pop_on        = (**old_h).pop_on;
  310.                     (**h).push_sound    = (**old_h).push_sound;
  311.                     (**h).pop_sound        = (**old_h).pop_sound;
  312.                     (**h).push_key[0]    = (**old_h).push_key[0];
  313.                     (**h).push_key[1]    = (**old_h).push_key[1];
  314.                     (**h).push_key[2]    = (**old_h).push_key[2];
  315.                     (**h).push_key[3]    = (**old_h).push_key[3];
  316.                     (**h).pop_key[0]    = (**old_h).pop_key[0];
  317.                     (**h).pop_key[1]    = (**old_h).pop_key[1];
  318.                     (**h).pop_key[2]    = (**old_h).pop_key[2];
  319.                     (**h).pop_key[3]    = (**old_h).pop_key[3];
  320.                     (**h).show_init_icon= (**old_h).show_init_icon;
  321.                     (**h).no_marquee    = false;
  322.                     (**h).drag_key[0]    = false;
  323.                     (**h).drag_key[1]    = false;
  324.                     (**h).drag_key[2]    = false;
  325.                     (**h).drag_key[3]    = true;
  326.                     ReleaseResource((Handle)old_h);
  327.                     save_setting(h, &pf);
  328.                 }
  329.             }
  330.         }
  331.         CloseResFile(pf.RsrcRefNum);
  332.     }
  333.     else if(er == OPEN_ERROR) {
  334.         h = (init_data_hdl)NewHandleSys(sizeof(init_data));
  335.         if(h) {
  336.             (**h).drag_on        = true;
  337.             (**h).grow_on        = true;
  338.             (**h).push_on        = true;
  339.             (**h).pop_on        = true;
  340.             (**h).push_sound    = true;
  341.             (**h).pop_sound        = true;
  342.             (**h).push_key[0]    = false;
  343.             (**h).push_key[1]    = true;
  344.             (**h).push_key[2]    = false;
  345.             (**h).push_key[3]    = false;
  346.             (**h).pop_key[0]    = true;
  347.             (**h).pop_key[1]    = false;
  348.             (**h).pop_key[2]    = false;
  349.             (**h).pop_key[3]    = false;
  350.             (**h).show_init_icon= true;
  351.             (**h).no_marquee    = false;
  352.             (**h).drag_key[0]    = false;
  353.             (**h).drag_key[1]    = false;
  354.             (**h).drag_key[2]    = false;
  355.             (**h).drag_key[3]    = true;
  356.             save_setting(h, &pf);
  357.         }
  358.     }
  359.     UseResFile(saved_ref_num);
  360.     return(h);
  361. }
  362.  
  363. void save_setting(init_data_hdl sysheap_data_hdl, prefs_file *pf_ptr)
  364. {
  365.     Handle            h;
  366.     init_data_hdl    work_h;
  367.     OSErr            err;
  368.     FInfo            f_info;
  369.  
  370.     HCreateResFile(pf_ptr->vRefNum, pf_ptr->DirID, PREFS_TITLE);
  371.     f_info.fdType = 'pref';
  372.     f_info.fdCreator = CREATOR;
  373.     f_info.fdFlags = 0;
  374.     HSetFInfo(pf_ptr->vRefNum, pf_ptr->DirID, PREFS_TITLE, &f_info);
  375.     open_prefs_file(pf_ptr);    //    HSetFInfo close a resource file, so you must open again.
  376.  
  377.     work_h = (init_data_hdl)NewHandle(sizeof(init_data));
  378.     if(work_h) {
  379.         **work_h = **sysheap_data_hdl;
  380.         if(h = Get1Resource(SETTING_RSRC, RSRC_NUMBER_BASE + 1))
  381.             RmveResource(h);
  382.         AddResource((Handle)work_h, SETTING_RSRC, RSRC_NUMBER_BASE + 1, "\p");
  383.         ReleaseResource((Handle)work_h);
  384.         CloseResFile(pf_ptr->RsrcRefNum);
  385.     }
  386. }
  387.  
  388. int open_prefs_file(prefs_file *pf_ptr)
  389. {
  390.     OSErr        er;
  391.     int            rn;
  392.     
  393.     er = FindFolder(kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder,
  394.                         &(pf_ptr->vRefNum), &(pf_ptr->DirID));
  395.     if(er == 0) {
  396.         rn = HOpenResFile(pf_ptr->vRefNum, pf_ptr->DirID, PREFS_TITLE, fsRdWrPerm);
  397.         if(rn != -1) {
  398.             pf_ptr->RsrcRefNum = rn;
  399.             return(NO_ERROR);
  400.         }
  401.         return(OPEN_ERROR);
  402.     }
  403.     return(CAUTION_ERROR);
  404. }
  405.  
  406. //    trap routines -----------------------------------
  407.  
  408. pascal Boolean my_track_go_away(WindowPtr wp, Point mp)
  409. {
  410.     KeyMap        my_keymap;
  411.     Boolean        f;
  412.     
  413.     SetUpA4();
  414.     GetKeys(my_keymap);
  415.     if(    (**setting_hdl).pop_on        &&
  416.         (key2[0] == BitTst(my_keymap, CONTROL_KEY))    &&
  417.         (key2[1] == BitTst(my_keymap, SHIFT_KEY))    &&
  418.         (key2[2] == BitTst(my_keymap, OPTION_KEY))    &&
  419.         (key2[3] == BitTst(my_keymap, COMMAND_KEY))    )
  420.             f = call_custom_go_away(wp, mp);
  421.     else    f = call_original_go_away(wp, mp);
  422.     RestoreA4();
  423.     return(f);
  424. }
  425.  
  426. pascal Boolean call_original_go_away(WindowPtr wp, Point mp)
  427. {
  428.     Boolean        f;
  429.  
  430.     f = (*TrackGoAwayProc)(wp, mp);
  431.     return(f);
  432. }
  433.  
  434. pascal Boolean call_custom_go_away(WindowPtr wp, Point mp)
  435. {
  436.     Boolean        f;
  437.     Point        pt;
  438.     GrafPtr        saved_port;
  439.     
  440.     f = call_original_go_away(wp, mp);
  441.     if(f) {
  442.         GetPort(&saved_port);
  443.         SetPort(wp);
  444.         MoveWindow(wp, std_state.left, std_state.top, false);
  445.         SetPort(saved_port);
  446.     }
  447.     if((**setting_hdl).pop_sound) {
  448.         if(TrapAvailable(_SndPlay) && my_pop_snd_hdl)
  449.             SndPlay(nil, my_pop_snd_hdl, false);
  450.         else SysBeep(1);
  451.     }
  452.     return(f);
  453. }
  454.  
  455. pascal void my_drag_window(WindowPtr wp, Point mp, Rect *r)
  456. {
  457.     KeyMap        my_keymap;
  458.     Rect        dummy_rect;
  459.     
  460.     SetUpA4();
  461.     GetKeys(my_keymap);
  462.     if(!setting_hdl)                    call_original_drag(wp, mp, r);
  463.     else if((**setting_hdl).no_marquee    &&
  464.             (key3[0] == BitTst(my_keymap, CONTROL_KEY))    &&
  465.             (key3[1] == BitTst(my_keymap, SHIFT_KEY))    &&
  466.             (key3[2] == BitTst(my_keymap, OPTION_KEY))    &&
  467.             (key3[3] == BitTst(my_keymap, COMMAND_KEY))    )
  468.                                         call_no_marquee_drag(wp, mp, r);
  469.     else if((**setting_hdl).push_on        &&
  470.             (key1[0] == BitTst(my_keymap, CONTROL_KEY))    &&
  471.             (key1[1] == BitTst(my_keymap, SHIFT_KEY))    &&
  472.             (key1[2] == BitTst(my_keymap, OPTION_KEY))    &&
  473.             (key1[3] == BitTst(my_keymap, COMMAND_KEY))    )
  474.                                         call_push_window(wp, mp, r);
  475.     else if((**setting_hdl).pop_on        &&
  476.             (key2[0] == BitTst(my_keymap, CONTROL_KEY))    &&
  477.             (key2[1] == BitTst(my_keymap, SHIFT_KEY))    &&
  478.             (key2[2] == BitTst(my_keymap, OPTION_KEY))    &&
  479.             (key2[3] == BitTst(my_keymap, COMMAND_KEY))    )
  480.                                         call_pop_window(wp, mp, r);
  481.     else if(!(**setting_hdl).drag_on)    call_original_drag(wp, mp, r);
  482.     else  call_custom_drag(wp, mp, r);
  483.     RestoreA4();
  484. }
  485.  
  486. pascal void call_original_drag(WindowPtr wp, Point mp, Rect *r)
  487. {
  488.     (*DragWindowProc)(wp, mp, r);
  489. }
  490.  
  491. pascal long my_grow_window(WindowPtr wp, Point mp, Rect *r)
  492. {
  493.     KeyMap        my_keymap;
  494.     long        v;
  495.     
  496.     SetUpA4();
  497.     GetKeys(my_keymap);
  498.  
  499.     if(!setting_hdl)
  500.         v = call_original_grow(wp, mp, r);
  501.     else if(!(**setting_hdl).grow_on)
  502.         v = call_original_grow(wp, mp, r);
  503.     else  v = call_custom_grow(wp, mp, r);
  504.     RestoreA4();
  505.     return(v);
  506. }
  507.  
  508. pascal long call_original_grow(WindowPtr wp, Point mp, Rect *r)
  509. {
  510.     long        v;
  511.     
  512.     v = (*GrowWindowProc)(wp, mp, r);
  513.     
  514.     return(v);
  515. }
  516.  
  517. pascal void call_push_window(WindowPtr wp, Point mp, Rect *r)
  518. {
  519.     GrafPtr            saved_port;
  520.     
  521.     GetPort(&saved_port);
  522.     SetPort(wp);
  523.     std_state.left    = (**((WindowPeek)wp)->contRgn).rgnBBox.left;
  524.     std_state.top    = (**((WindowPeek)wp)->contRgn).rgnBBox.top;
  525.     SetPort(saved_port);
  526.     if((**setting_hdl).push_sound) {
  527.         if(TrapAvailable(_SndPlay) && my_push_snd_hdl)
  528.             SndPlay(nil, my_push_snd_hdl, false);
  529.         else    SysBeep(1);
  530.     }
  531.     return;
  532. }
  533.  
  534. pascal void call_pop_window(WindowPtr wp, Point mp, Rect *r)
  535. {
  536.     GrafPtr        saved_port;
  537.  
  538.     GetPort(&saved_port);
  539.     SetPort(wp);
  540.     MoveWindow(wp, std_state.left, std_state.top, false);
  541.     SetPort(saved_port);
  542.     if((**setting_hdl).pop_sound) {
  543.         if(TrapAvailable(_SndPlay) && my_pop_snd_hdl)
  544.             SndPlay(nil, my_pop_snd_hdl, false);
  545.         else    SysBeep(1);
  546.     }
  547.     return;
  548. }
  549.     
  550.     
  551. pascal void    call_custom_drag(WindowPtr    wp,    Point mp, Rect *r)
  552. {
  553.     GrafPtr        saved_port;
  554.     Point        old_pt_g, new_pt_g, p, spread_l_to_g, saved_pt_g, mp_g,
  555.                 offset, w_g, saved_pn_size;
  556.     WindowPeek    wpk;
  557.     Boolean        h_changed, v_changed, color_qd;
  558.     Rect        wpk_rect_g, saved_rect_g, marquee_spread_l, c_rect_g, s_rect_g,
  559.                 gap, r_g, work_r;
  560.     short        c_width, c_height, screen_width, screen_height;
  561.     PenState    saved_pen_state;
  562.     char        i;
  563.     RgnHandle    new_rgn, saved_vis_rgn, saved_clip_rgn, s_rgn_g, marquee_rgn_spread_l;
  564.     RGBColor    fore_color, back_color;
  565.     PixPatHandle    saved_pn_pp_hdl, saved_fill_pp_hdl, saved_bk_pp_hdl,
  566.                     dummy_pn_pp_hdl, dummy_fill_pp_hdl, dummy_bk_pp_hdl;
  567.     Pattern        saved_bk_pat, saved_fill_pat, saved_pn_pat;
  568.     short        saved_pn_mode;
  569.     
  570.     
  571.     GetPort(&saved_port);
  572.  
  573.     if(color_qd = TrapAvailable(_GetForeColor)) {
  574.         GetForeColor(&fore_color);
  575.         GetBackColor(&back_color);
  576.         dummy_bk_pp_hdl = NewPixPat();
  577.         dummy_pn_pp_hdl = NewPixPat();
  578.         dummy_fill_pp_hdl = NewPixPat();
  579.         saved_bk_pp_hdl = ((CGrafPtr)wp)->bkPixPat;
  580.         saved_pn_pp_hdl = ((CGrafPtr)wp)->pnPixPat;
  581.         saved_fill_pp_hdl = ((CGrafPtr)wp)->fillPixPat;
  582.         ((CGrafPtr)wp)->bkPixPat = dummy_bk_pp_hdl;
  583.         ((CGrafPtr)wp)->pnPixPat = dummy_pn_pp_hdl;
  584.         ((CGrafPtr)wp)->fillPixPat = dummy_fill_pp_hdl;
  585.             //    PenPat changes members of pnPixPat structure if current GrafPort
  586.             //    is color GrafPort.
  587.             //    If current GrafPort is color only, use CopyPixPat.
  588.     }
  589.     else {
  590.         copy_pattern(wp->pnPat, saved_pn_pat);
  591.         copy_pattern(wp->bkPat, saved_bk_pat);
  592.         copy_pattern(wp->fillPat, saved_fill_pat);
  593.     }
  594.     saved_pn_mode = wp->pnMode;
  595.     saved_pn_size = wp->pnSize;
  596.         //    I used to use GetPenState. But I feel that GetPenState offen
  597.         //    work properly. So I copy pnSize and pnMode direct.
  598.  
  599.     SetPort(wp);
  600.     mp_g = mp;
  601.  
  602.     new_rgn            = NewRgn();
  603.     saved_vis_rgn    = NewRgn();
  604.     saved_clip_rgn    = NewRgn();
  605.         //    vis & clipRgn seem not to be changed if you change without using system
  606.         //  routines like SetClip. Especially visRgn (it has no system routine).
  607.     
  608.     marquee_rgn_spread_l = NewRgn();
  609.     
  610.     CopyRgn(wp->visRgn,        saved_vis_rgn);        //    Don't forget NewRgn before CopyRgn!
  611.     CopyRgn(wp->clipRgn,    saved_clip_rgn);
  612.     
  613.     saved_pt_g.h = wp->portRect.right;
  614.     saved_pt_g.v = wp->portRect.bottom;
  615.     LocalToGlobal(&saved_pt_g);
  616.     saved_rect_g.right    = saved_pt_g.h;
  617.     saved_rect_g.bottom    = saved_pt_g.v;
  618.     saved_pt_g.h = wp->portRect.left;
  619.     saved_pt_g.v = wp->portRect.top;
  620.     LocalToGlobal(&saved_pt_g);
  621.     saved_rect_g.left    = saved_pt_g.h;
  622.     saved_rect_g.top    = saved_pt_g.v;
  623.         //    'g' in 'saved_rect_g' etc. mean global coordinates.
  624.         //    'saved_pt_g' shows the top-left corner of portRect.
  625.     
  626.     offset.h    = mp_g.h - saved_pt_g.h;    
  627.     offset.v    = mp_g.v - saved_pt_g.v;    
  628.         //    'offset's are differences between the coordinates of
  629.         //    mouse point and top-left of portRect. Normally plus.
  630.     
  631.     c_rect_g    = (**((WindowPeek)wp)->contRgn).rgnBBox;
  632.     s_rgn_g        = ((WindowPeek)wp)->strucRgn;
  633.     s_rect_g    = (**s_rgn_g).rgnBBox;
  634.     
  635.     gap.left    = saved_rect_g.left    - s_rect_g.left;                                    
  636.     gap.top        = saved_rect_g.top    - s_rect_g.top;                                    
  637.     gap.right    = s_rect_g.right    - saved_rect_g.right;
  638.     gap.bottom    = s_rect_g.bottom    - saved_rect_g.bottom;
  639.         //    These 'gap's are differences between portRect and
  640.         //    structure rectangle. These are also plus.
  641.     
  642.     c_width        = saved_rect_g.right    - saved_rect_g.left;
  643.     c_height    = saved_rect_g.bottom    - saved_rect_g.top;
  644.     screen_width    = gray_rect.right    - gray_rect.left;
  645.     screen_height    = gray_rect.bottom    - gray_rect.top    - menu_bar_height;
  646.     
  647.     PortSize(screen_width, screen_height);
  648.         //    Spread current grafport to draw the marquee.
  649.     
  650.     MovePortTo(gray_rect.left, gray_rect.top + menu_bar_height);
  651. //    PortChanged((GrafPtr)wp);
  652.     RectRgn(new_rgn, &(wp->portRect));
  653.     UnionRgn(new_rgn, wp->visRgn,    wp->visRgn);
  654.     UnionRgn(new_rgn, wp->clipRgn,    wp->clipRgn);
  655.     DisposeRgn(new_rgn);
  656. //    PortChanged((GrafPtr)wp);
  657.     SetPort(wp);
  658.         //    vis & clipRgn are setted here.
  659.         //    PortChanged is sometimes unimplemented (especially old Mac).
  660.         //    So you had better to use SetPort if you want to change property of grafport
  661.         //    without use of system routines.
  662.     
  663.     p.h = s_rect_g.left;
  664.     p.v = s_rect_g.top;
  665.     GlobalToLocal(&p);
  666.     spread_l_to_g.h = s_rect_g.left    - p.h;
  667.     spread_l_to_g.v = s_rect_g.top    - p.v;
  668.         //    These 'spread_l_to_g's are differences between 
  669.         //    'spreaded' local coordinates and global.
  670.         //    Adding spread_l_to_g converts suspended local coordinates to global.
  671.         //    And substracting spread_l_to_g converts global to suspended local.
  672.     
  673.     r_g = *r;
  674.     work_r = gray_rect;
  675.     work_r.top += menu_bar_height + 2;
  676.     SectRect(&r_g, &work_r, &r_g);
  677.     
  678.     CopyRgn(s_rgn_g, marquee_rgn_spread_l);
  679.     OffsetRgn(marquee_rgn_spread_l, - spread_l_to_g.h, - spread_l_to_g.v);
  680.         //    Rgn is prepared as Handle. So "marquee_rgn = s_rgn" is wrong if you don't
  681.         //    want to touch original strucRgn.
  682.         //    And move the marquee to the proper spreaded local point.
  683.     
  684.     PenSize(1,1);
  685.     PenMode(patXor);
  686.     PenPat(my_qd_globals.gray);
  687.     
  688.     FrameRgn(marquee_rgn_spread_l);
  689.     
  690.     old_pt_g = mp_g;
  691.     
  692.     w_g.h = saved_rect_g.left;
  693.     w_g.v = saved_rect_g.top;
  694.     
  695.     while(StillDown()) {
  696.         GetMouse(&new_pt_g);
  697.         LocalToGlobal(&new_pt_g);
  698.         if(PtInRect(new_pt_g, &r_g)) {
  699.             if    (!EqualPt(new_pt_g,    old_pt_g))    {
  700.                 w_g.h = new_pt_g.h - offset.h;
  701.                 w_g.v = new_pt_g.v - offset.v;
  702.                 h_changed = v_changed = false;
  703.                 wpk = (WindowPeek)FrontWindow();
  704.                 while(wpk) {
  705.                     if(wpk != (WindowPeek)wp) {
  706.                         wpk_rect_g = (**wpk->strucRgn).rgnBBox;
  707.                         if(!h_changed &&(abs(wpk_rect_g.left
  708.                                 - (w_g.h - gap.left)) <= 5))    {
  709.                             w_g.h = wpk_rect_g.left + gap.left;
  710.                             h_changed = true;
  711.                         }
  712.                         if(!h_changed &&(abs(wpk_rect_g.right
  713.                                 - (w_g.h - gap.left)) <= 5)) {
  714.                             w_g.h = wpk_rect_g.right + gap.left;
  715.                             h_changed = true;
  716.                         }
  717.                         if(!h_changed &&(abs(wpk_rect_g.left
  718.                                 - (w_g.h + c_width + gap.right)) <= 5)) {
  719.                             w_g.h = wpk_rect_g.left - c_width - gap.right;
  720.                             h_changed = true;
  721.                         }
  722.                         if(!h_changed &&(abs(wpk_rect_g.right
  723.                                 - (w_g.h + c_width + gap.right)) <= 5)) {
  724.                             w_g.h = wpk_rect_g.right - c_width - gap.right;
  725.                             h_changed = true;
  726.                         }
  727.                         if(!v_changed &&(abs(wpk_rect_g.top
  728.                                 - (w_g.v - gap.top)) <= 5)) {
  729.                             w_g.v = wpk_rect_g.top + gap.top;
  730.                             v_changed = true;
  731.                         }
  732.                         if(!v_changed &&(abs(wpk_rect_g.bottom
  733.                                 - (w_g.v - gap.top)) <= 5)) {
  734.                             w_g.v = wpk_rect_g.bottom + gap.top;
  735.                             v_changed = true;
  736.                         }
  737.                         if(!v_changed &&(abs(wpk_rect_g.top
  738.                             - (w_g.v + c_height + gap.bottom)) <= 5)) {
  739.                             w_g.v = wpk_rect_g.top - c_height - gap.bottom;
  740.                             v_changed = true;
  741.                         }
  742.                         if(!v_changed &&(abs(wpk_rect_g.bottom
  743.                             - (w_g.v + c_height + gap.bottom)) <= 5)) {
  744.                             w_g.v = wpk_rect_g.bottom - c_height- gap.bottom;
  745.                             v_changed = true;
  746.                         }
  747.                         wpk    = wpk->nextWindow;
  748.                         if(h_changed && v_changed)        wpk = (WindowPeek)0;
  749.                     }
  750.                     else {
  751.                         wpk = wpk->nextWindow;
  752.                     }
  753.                     
  754.                 }
  755.                 FrameRgn(marquee_rgn_spread_l);
  756.             
  757.                 OffsetRgn(marquee_rgn_spread_l,
  758.                     w_g.h - gap.left    - spread_l_to_g.h
  759.                                 - (**marquee_rgn_spread_l).rgnBBox.left,
  760.                     w_g.v - gap.top        - spread_l_to_g.v
  761.                                 - (**marquee_rgn_spread_l).rgnBBox.top);
  762.                         //    'w_g's show top-left corner of portRect.
  763.                         //    And portRect has local coordinates.
  764.                                 
  765.                 FrameRgn(marquee_rgn_spread_l);
  766.                 old_pt_g = new_pt_g;
  767.             }
  768.         }    
  769.     }
  770.     FrameRgn(marquee_rgn_spread_l);
  771.     PortSize(saved_rect_g.right        - saved_rect_g.left,
  772.              saved_rect_g.bottom    - saved_rect_g.top);
  773.     MovePortTo(saved_pt_g.h, saved_pt_g.v);
  774.     CopyRgn(saved_vis_rgn,        wp->visRgn);
  775.     CopyRgn(saved_clip_rgn,        wp->clipRgn);
  776. //    PortChanged((GrafPtr)wp);
  777.     MoveWindow(wp, w_g.h, w_g.v, false);
  778.     DisposeRgn(marquee_rgn_spread_l);
  779.     DisposeRgn(saved_vis_rgn);
  780.     DisposeRgn(saved_clip_rgn);    //    Don't forget DisposeRgn!
  781.     SetPort(wp);
  782.     SetPort(saved_port);
  783.  
  784.     if(color_qd) {
  785.         RGBForeColor(&fore_color);
  786.         RGBBackColor(&back_color);
  787.         ((CGrafPtr)wp)->bkPixPat = saved_bk_pp_hdl;
  788.         ((CGrafPtr)wp)->pnPixPat = saved_pn_pp_hdl;
  789.         ((CGrafPtr)wp)->fillPixPat = saved_fill_pp_hdl;
  790.         DisposePixPat(dummy_bk_pp_hdl);
  791.         DisposePixPat(dummy_pn_pp_hdl);
  792.         DisposePixPat(dummy_fill_pp_hdl);
  793.     }
  794.     else {
  795.         copy_pattern(saved_bk_pat, wp->bkPat);
  796.         copy_pattern(saved_fill_pat, wp->fillPat);
  797.         copy_pattern(saved_pn_pat, wp->pnPat);
  798.     }
  799.     wp->pnSize = saved_pn_size;
  800.     wp->pnMode = saved_pn_mode;
  801. }
  802.  
  803. void copy_pattern(Pattern src_pat, Pattern dst_pat)
  804. {
  805.     int        i;
  806.     
  807.     for(i = 0; i <= 7; i++) {
  808.         dst_pat[i] = src_pat[i];
  809.     }
  810. }
  811.  
  812. pascal void call_no_marquee_drag(WindowPtr wp, Point mp, Rect *r)
  813. {
  814.     GrafPtr     saved_port;
  815.     Point        old_pt, new_pt;
  816.     short        offset_h, offset_v;
  817.     WindowPeek    wpk;
  818.     Boolean        h_changed, v_changed;
  819.     Rect        wpk_rect;
  820.     short        w_width, w_height;
  821.     short        w_left, w_top;
  822.     short        gap_left, gap_top, gap_right, gap_bottom;
  823.     
  824.     GetPort(&saved_port);
  825.     SetPort(wp);
  826.     offset_h = mp.h - (**((WindowPeek)wp)->contRgn).rgnBBox.left;
  827.     offset_v = mp.v - (**((WindowPeek)wp)->contRgn).rgnBBox.top;
  828.     gap_left   = (**((WindowPeek)wp)->contRgn).rgnBBox.left    - (**((WindowPeek)wp)->strucRgn).rgnBBox.left;
  829.     gap_top    = (**((WindowPeek)wp)->contRgn).rgnBBox.top     - (**((WindowPeek)wp)->strucRgn).rgnBBox.top;
  830.     gap_right  = (**((WindowPeek)wp)->strucRgn).rgnBBox.right  - (**((WindowPeek)wp)->contRgn).rgnBBox.right;
  831.     gap_bottom = (**((WindowPeek)wp)->strucRgn).rgnBBox.bottom - (**((WindowPeek)wp)->contRgn).rgnBBox.bottom;
  832.     w_width = (**((WindowPeek)wp)->contRgn).rgnBBox.right
  833.             - (**((WindowPeek)wp)->contRgn).rgnBBox.left;
  834.     w_height = (**((WindowPeek)wp)->contRgn).rgnBBox.bottom
  835.             - (**((WindowPeek)wp)->contRgn).rgnBBox.top;
  836.     old_pt = mp;
  837.     while (StillDown()) {
  838.         GetMouse(&new_pt);
  839.         LocalToGlobal(&new_pt);
  840.         if (PtInRect(new_pt, r)) {
  841.             if (!EqualPt(new_pt, old_pt)) {
  842.                 w_left = new_pt.h - offset_h;
  843.                 w_top  = new_pt.v - offset_v;
  844.                 h_changed = v_changed = false;
  845.  
  846.                 wpk = (WindowPeek)FrontWindow();
  847.                 while(wpk)    {
  848.                     if(wpk != (WindowPeek)wp) {
  849.                         wpk_rect = (**wpk->strucRgn).rgnBBox;
  850.                         if (!h_changed &&(abs(wpk_rect.left - (w_left - gap_left)) <= 5)) {
  851.                             w_left = wpk_rect.left + gap_left;
  852.                             h_changed = true;
  853.                         }
  854.                         if (!h_changed &&(abs(wpk_rect.right - (w_left - gap_left)) <= 5)) {
  855.                             w_left = wpk_rect.right + gap_left;
  856.                             h_changed = true;
  857.                         }
  858.                         if (!h_changed &&(abs(wpk_rect.left - (w_left + w_width + gap_right)) <= 5)) {
  859.                             w_left = wpk_rect.left - w_width - gap_right;
  860.                             h_changed = true;
  861.                         }
  862.                         if (!h_changed &&(abs(wpk_rect.right - (w_left + w_width + gap_right)) <= 5)) {
  863.                             w_left = wpk_rect.right - w_width - gap_right;
  864.                             h_changed = true;
  865.                         }
  866.                         if (!v_changed &&(abs(wpk_rect.top - (w_top - gap_top)) <= 5)) {
  867.                             w_top = wpk_rect.top + gap_top;
  868.                             v_changed = true;
  869.                         }
  870.                         if (!v_changed &&(abs(wpk_rect.bottom - (w_top - gap_top)) <= 5)) {
  871.                             w_top = wpk_rect.bottom + gap_top;
  872.                             v_changed = true;
  873.                         }
  874.                         if (!v_changed &&(abs(wpk_rect.top - (w_top + w_height + gap_bottom)) <= 5)) {
  875.                             w_top = wpk_rect.top - w_height - gap_bottom;
  876.                             v_changed = true;
  877.                         }
  878.                         if (!v_changed &&(abs(wpk_rect.bottom - (w_top + w_height + gap_bottom)) <= 5)) {
  879.                             w_top = wpk_rect.bottom - w_height - gap_bottom;
  880.                             v_changed = true;
  881.                         }
  882.                         wpk = wpk->nextWindow;
  883.                         if(h_changed && v_changed)    wpk = (WindowPeek)0;
  884.                     } else {
  885.                         wpk = wpk->nextWindow;
  886.                     }
  887.                 }
  888.             
  889.                 MoveWindow(wp, w_left, w_top, false);
  890.                 old_pt = new_pt;
  891.             }
  892.         }
  893.     }
  894.     SetPort(saved_port);
  895. }
  896.  
  897.  
  898. pascal long call_custom_grow(WindowPtr wp, Point mp, Rect *r)
  899. {
  900.     GrafPtr            saved_port;
  901.     Point            old_pt_g, new_pt_g, p, spread_l_to_g, saved_pt_g, mp_g, offset,
  902.                     w_g, old_l_to_g, saved_pn_size;
  903.     WindowPeek        wpk;
  904.     Boolean            h_changed, v_changed, color_qd;
  905.     KeyMap            my_keymap;
  906.     Rect            wpk_rect_g, saved_rect_g, marquee_spread_l, c_rect_g, s_rect_g,
  907.                     gap, r_g;
  908.     short            c_width, c_height, screen_width, screen_height;
  909.     long            return_value = 0;
  910.     PenState        saved_pen_state;
  911.     RGBColor        fore_color, back_color;
  912.     long            l;
  913.     RgnHandle        new_rgn, saved_vis_rgn, saved_clip_rgn;
  914.     PixPatHandle    saved_pn_pp_hdl, saved_fill_pp_hdl, saved_bk_pp_hdl,
  915.                     dummy_pn_pp_hdl, dummy_fill_pp_hdl, dummy_bk_pp_hdl;
  916.     Pattern            saved_bk_pat, saved_fill_pat, saved_pn_pat;
  917.     short            saved_pn_mode;
  918.         
  919.     GetPort(&saved_port);
  920.     if(color_qd = TrapAvailable(_GetForeColor)) {
  921.         GetForeColor(&fore_color);
  922.         GetBackColor(&back_color);
  923.         dummy_bk_pp_hdl = NewPixPat();
  924.         dummy_pn_pp_hdl = NewPixPat();
  925.         dummy_fill_pp_hdl = NewPixPat();
  926.         saved_bk_pp_hdl = ((CGrafPtr)wp)->bkPixPat;
  927.         saved_pn_pp_hdl = ((CGrafPtr)wp)->pnPixPat;
  928.         saved_fill_pp_hdl = ((CGrafPtr)wp)->fillPixPat;
  929.         ((CGrafPtr)wp)->bkPixPat = dummy_bk_pp_hdl;
  930.         ((CGrafPtr)wp)->pnPixPat = dummy_pn_pp_hdl;
  931.         ((CGrafPtr)wp)->fillPixPat = dummy_fill_pp_hdl;
  932.     }
  933.     else {
  934.         copy_pattern(wp->pnPat, saved_pn_pat);
  935.         copy_pattern(wp->bkPat, saved_bk_pat);
  936.         copy_pattern(wp->fillPat, saved_fill_pat);
  937.     }
  938.     saved_pn_mode = wp->pnMode;
  939.     saved_pn_size = wp->pnSize;
  940.     
  941.     SetPort(wp);
  942.     mp_g = mp;
  943.     
  944.     old_l_to_g.h = wp->portRect.left;
  945.     old_l_to_g.v = wp->portRect.top;
  946.     LocalToGlobal(&old_l_to_g);
  947.         //    Adding old_l_to_g converts old (not spreaded) local coordinates to global.
  948.     
  949.     r_g = *r;
  950.         //    r shows the restrict "size" here.
  951.     
  952.     if(r_g.right > gray_rect.right)
  953.         r_g.right  = gray_rect.right;
  954.             //    Set maximum window size(horizontal) to appropriate size.
  955.                     
  956.     if(r_g.bottom > gray_rect.bottom)
  957.         r_g.bottom = gray_rect.bottom;
  958.             //    Set maximum window size(vertical) to appropriate size.
  959.             
  960.     OffsetRect(&r_g, old_l_to_g.h, old_l_to_g.v);
  961.         //    Here, r shows the restrict rectangle (coordinations).
  962.     
  963.     new_rgn = NewRgn();
  964.     saved_vis_rgn    = NewRgn();
  965.     saved_clip_rgn    = NewRgn();
  966.     
  967.     CopyRgn(wp->visRgn,        saved_vis_rgn);
  968.     CopyRgn(wp->clipRgn,    saved_clip_rgn);
  969.     
  970.     saved_pt_g.h = wp->portRect.right;
  971.     saved_pt_g.v = wp->portRect.bottom;
  972.     LocalToGlobal(&saved_pt_g);
  973.     saved_rect_g.right    = saved_pt_g.h;
  974.     saved_rect_g.bottom    = saved_pt_g.v;
  975.     saved_pt_g.h = wp->portRect.left;
  976.     saved_pt_g.v = wp->portRect.top;
  977.     LocalToGlobal(&saved_pt_g);
  978.     saved_rect_g.left    = saved_pt_g.h;
  979.     saved_rect_g.top    = saved_pt_g.v;
  980.     
  981.     offset.h = saved_rect_g.right    - mp.h;
  982.     offset.v = saved_rect_g.bottom    - mp.v;
  983.     
  984.     c_rect_g    = (**((WindowPeek)wp)->contRgn).rgnBBox;
  985.     s_rect_g    = (**((WindowPeek)wp)->strucRgn).rgnBBox;
  986.     
  987.     gap.left    = saved_rect_g.left    - s_rect_g.left;
  988.     gap.top        = saved_rect_g.top    - s_rect_g.top;
  989.     gap.right    = s_rect_g.right        - saved_rect_g.right;
  990.     gap.bottom    = s_rect_g.bottom        - saved_rect_g.bottom;
  991.     
  992.     c_width        = saved_rect_g.right    - saved_rect_g.left;
  993.     c_height    = saved_rect_g.bottom    - saved_rect_g.top;
  994.     screen_width    = gray_rect.right    - s_rect_g.left;
  995.     screen_height    = gray_rect.bottom    - s_rect_g.top;
  996.     
  997.     PortSize(screen_width, screen_height);
  998.     MovePortTo(s_rect_g.left, s_rect_g.top);
  999. //    PortChanged((GrafPtr)wp);
  1000.     RectRgn(new_rgn, &(wp->portRect));
  1001.     UnionRgn(new_rgn, wp->visRgn,    wp->visRgn);
  1002.     UnionRgn(new_rgn, wp->clipRgn,    wp->clipRgn);
  1003.     DisposeRgn(new_rgn);
  1004. //    PortChanged((GrafPtr)wp);
  1005.     SetPort(wp);
  1006.     
  1007.     p.h = s_rect_g.left;
  1008.     p.v = s_rect_g.top;
  1009.     GlobalToLocal(&p);
  1010.     spread_l_to_g.h = s_rect_g.left    - p.h;
  1011.     spread_l_to_g.v = s_rect_g.top    - p.v;
  1012.     
  1013.     marquee_spread_l.left    = s_rect_g.left - spread_l_to_g.h;
  1014.     marquee_spread_l.top    = s_rect_g.top  - spread_l_to_g.v;
  1015.     marquee_spread_l.right    = s_rect_g.right    - spread_l_to_g.h + 1;
  1016.     marquee_spread_l.bottom    = s_rect_g.bottom    - spread_l_to_g.v + 1;
  1017.         //    '+ 1' is added because sysytem routine does so.
  1018.     
  1019.     PenSize(1,1);
  1020.     PenMode(patXor);
  1021.     PenPat(my_qd_globals.gray);
  1022.     
  1023.     draw_marquee(&marquee_spread_l, &gap);
  1024.     
  1025.     old_pt_g = mp_g;
  1026.     w_g.h = saved_rect_g.right;
  1027.     w_g.v = saved_rect_g.bottom;
  1028.     
  1029.     while(StillDown()) {
  1030.         GetMouse(&new_pt_g);
  1031.         new_pt_g.h += offset.h;
  1032.         new_pt_g.v += offset.v;
  1033.         LocalToGlobal(&new_pt_g);
  1034.         if(!PtInRect(new_pt_g, &r_g)) {
  1035.             //    This checks too small or too larger window size.
  1036.             
  1037.             l = PinRect(&r_g, new_pt_g);
  1038.             if(new_pt_g.v != HiWord(l))
  1039.                 new_pt_g.v = HiWord(l);
  1040.             if(new_pt_g.h != LoWord(l))
  1041.                 new_pt_g.h = LoWord(l);
  1042.         }
  1043.         if(!EqualPt(new_pt_g, old_pt_g)) {
  1044.             w_g.h = new_pt_g.h;
  1045.             w_g.v = new_pt_g.v;
  1046.             h_changed    = v_changed = false;
  1047.             GetKeys(my_keymap);
  1048.             if(BitTst(&my_keymap, OPTION_KEY)) {
  1049.                 // If option key is pressed, the window grows every 5 pixels.
  1050.                 
  1051.                 w_g.h = (w_g.h / 5) * 5;
  1052.                 w_g.v = (w_g.v / 5) * 5;
  1053.             }
  1054.             else {
  1055.                 wpk = (WindowPeek)FrontWindow();
  1056.                 while(wpk) {
  1057.                     if(wpk != (WindowPeek)wp) {
  1058.                         wpk_rect_g = (**wpk->strucRgn).rgnBBox;
  1059.                         if (!h_changed && (abs(wpk_rect_g.left
  1060.                                 - (w_g.h + gap.right)) <= 5)) {
  1061.                             w_g.h = wpk_rect_g.left - gap.right;
  1062.                             h_changed = true;
  1063.                         }
  1064.                         if(!h_changed && (abs(wpk_rect_g.right
  1065.                                 - (w_g.h + gap.right)) <= 5)) {
  1066.                             w_g.h = wpk_rect_g.right - gap.right;
  1067.                             h_changed = true;
  1068.                         }
  1069.                     
  1070.                         if(!v_changed && (abs(wpk_rect_g.top
  1071.                                 - (w_g.v + gap.bottom)) <= 5)) {
  1072.                             w_g.v = wpk_rect_g.top - gap.bottom;
  1073.                             v_changed = true;
  1074.                         }
  1075.                         if(!v_changed    && (abs(wpk_rect_g.bottom
  1076.                                 - (w_g.v    + gap.bottom)) <= 5)) {
  1077.                             w_g.v = wpk_rect_g.bottom - gap.bottom;
  1078.                             v_changed = true;
  1079.                         }
  1080.                     
  1081.                         wpk = wpk->nextWindow;
  1082.                         if(h_changed && v_changed)
  1083.                             wpk = (WindowPeek)0;
  1084.                     }
  1085.                     else {
  1086.                         wpk = wpk->nextWindow;
  1087.                     }
  1088.                 }
  1089.             }
  1090.             draw_marquee(&marquee_spread_l, &gap);
  1091.             
  1092.             marquee_spread_l.right    = w_g.h    + gap.right        - spread_l_to_g.h - 1;
  1093.             marquee_spread_l.bottom    = w_g.v    + gap.bottom    - spread_l_to_g.v - 1;
  1094.                 //    '- 1' is added because '+ 1' was added :-)
  1095.             
  1096.             draw_marquee(&marquee_spread_l, &gap);
  1097.             
  1098.             c_width        = w_g.h    - saved_rect_g.left;
  1099.             c_height    = w_g.v    - saved_rect_g.top;
  1100.             old_pt_g = new_pt_g;
  1101.         }
  1102.     }
  1103.     
  1104.     draw_marquee(&marquee_spread_l, &gap);
  1105.     
  1106.     PortSize(saved_rect_g.right        - saved_rect_g.left, 
  1107.              saved_rect_g.bottom    - saved_rect_g.top);
  1108.     MovePortTo(saved_pt_g.h, saved_pt_g.v);
  1109.     CopyRgn(saved_vis_rgn,        wp->visRgn);
  1110.     CopyRgn(saved_clip_rgn,        wp->clipRgn);
  1111. //    PortChanged((GrafPtr)wp);
  1112.     DisposeRgn(saved_vis_rgn);
  1113.     DisposeRgn(saved_clip_rgn);
  1114.     SetPort(wp);
  1115.     SetPort(saved_port);
  1116.     SetPenState(&saved_pen_state);
  1117.     if(color_qd) {
  1118.         RGBForeColor(&fore_color);
  1119.         RGBBackColor(&back_color);
  1120.         ((CGrafPtr)wp)->bkPixPat = saved_bk_pp_hdl;
  1121.         ((CGrafPtr)wp)->pnPixPat = saved_pn_pp_hdl;
  1122.         ((CGrafPtr)wp)->fillPixPat = saved_fill_pp_hdl;
  1123.         DisposePixPat(dummy_bk_pp_hdl);
  1124.         DisposePixPat(dummy_pn_pp_hdl);
  1125.         DisposePixPat(dummy_fill_pp_hdl);
  1126.     }
  1127.     else {
  1128.         copy_pattern(saved_pn_pat, wp->pnPat);
  1129.         copy_pattern(saved_bk_pat, wp->bkPat);
  1130.         copy_pattern(saved_fill_pat, wp->fillPat);
  1131.     }
  1132.     wp->pnSize = saved_pn_size;
  1133.     wp->pnMode = saved_pn_mode;
  1134.     
  1135.     if((mp.h != old_pt_g.h - offset.h) || (mp.v != old_pt_g.v - offset.v)) {
  1136.         return_value =        c_height;
  1137.         return_value <<=    16;
  1138.         return_value +=        c_width;
  1139.     }
  1140.     return(return_value);
  1141. }
  1142.  
  1143. void draw_marquee(Rect *marquee, Rect *gap)    
  1144.     //    This routine draws the complicated marquee used in call_custom_grow.
  1145. {
  1146.     FrameRect(marquee);
  1147.     MoveTo(marquee->left,    marquee->top + gap->top - 1);
  1148.     LineTo(marquee->right,    marquee->top + gap->top - 1);
  1149.     MoveTo(marquee->left,    marquee->bottom - 16);
  1150.     LineTo(marquee->right,    marquee->bottom - 16);
  1151.     MoveTo(marquee->right - 16, marquee->top + gap->top);
  1152.     LineTo(marquee->right - 16, marquee->bottom);
  1153.         //    16 means width of scroll bar.
  1154. }
  1155.  
  1156.  
  1157.